
#include <iostream>
#include <cxxabi.h>

#include "misc.hpp"
#include "debug.hpp"
using namespace wheels;

#define CALLSTACK_DEEP (128)

#if defined( __LINUX__ )
#include <dlfcn.h>
#include <execinfo.h>
void debug :: printCallstack() 
{
#if defined( __DEBUG__ )
    void* callstack[CALLSTACK_DEEP];
    const int max_depth = sizeof(callstack) / sizeof(callstack[0]);
    char** symbols;

    int stack_depth = backtrace(callstack, max_depth);
    symbols = backtrace_symbols(callstack, stack_depth);
	
    printf("%s\n-----------------------------------------------Callstack >>%s\n" , TRED , TNORMAL );
	int status = 0;
    for (int i = 1; i < stack_depth; ++i) {
		
		Dl_info dlinfo;  
        
        if (dladdr(callstack[i], &dlinfo) && dlinfo.dli_sname) {  
            const char * name = abi::__cxa_demangle(dlinfo.dli_sname, NULL, NULL, &status); 
            if( status != 0 ){
                name = dlinfo.dli_sname;
            }
            printf("%s----> [ %012p -- %012p ] %s %s\n", TRED, dlinfo.dli_fbase , dlinfo.dli_saddr ,name, TNORMAL);  
            if( status == 0 ){
                free( ( char *)name );
            }
        } else {  
            printf( "%s----> [ %012p -- %012p ] %s %s\n" , TRED , nullptr , nullptr ,symbols[i] , TNORMAL );
        }  

    }
	printf("%s-----------------------------------------------<< Callstack%s\n" , TRED , TNORMAL );

    free(symbols);
#endif
}

#elif defined( WINNT ) || defined( WIN32 )
#include <windows.h>
#include <DbgHelp.h>
void debug :: printCallstack() {
   /* void* callstack[CALLSTACK_DEEP];
    const int max_depth = sizeof(callstack) / sizeof(callstack[0]);

    HANDLE process = GetCurrentProcess();
    SymInitialize(process, NULL, TRUE);
    WORD frames = CaptureStackBackTrace(0, max_depth, callstack, NULL);

    MSG("\nCallstack:" , TYELLOW );

    SYMBOL_INFO* symbol = (SYMBOL_INFO*)malloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char));
    symbol->MaxNameLen = 255;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

    for (int i = 0; i < frames; ++i) {
        SymFromAddr(process, (DWORD64)(callstack[i]), 0, symbol);
        MSG_1( "%s 0X %p", TYELLOW, symbol->Name , (void*)symbol->Address );
    }

    free(symbol);
*/
}
#endif
